#ifndef STATE_LED_H
#define STATE_LED_H

// use first channel of 16 channels (started from zero)
#define LEDC_CHANNEL_0     0
// use 12 bit precission for LEDC timer
#define LEDC_TIMER_12_BIT  12
// use 5000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ     5000
#define ANALOG_VALUEMAX    1023
#define BLINK true
#define FADE false


void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = ANALOG_VALUEMAX) {
  // calculate duty, 4095 from 2 ^ 12 - 1
  uint32_t duty = (4095 / valueMax) * min(value, valueMax);
  // write duty to LEDC
  ledcWrite(channel, duty);
//   Serial.println(duty);
}


class LED_CONTRLLER{
    public:
        LED_CONTRLLER(uint8_t);
        void blink();
        void fade();
        void setPeriod(uint);
        void setMode(bool);
        void mainloop();
    

    private: 
        uint8_t pinNum;
        uint period = 500;
        bool state = false;
        int brightness = 0;    // how bright the LED is
        int fadeAmount;    // how many points to fade the LED by
};

LED_CONTRLLER :: LED_CONTRLLER(uint8_t pinNum){
    this->pinNum = pinNum;
    // pinMode(pinNum, OUTPUT);
    ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT);
    ledcAttachPin(pinNum, LEDC_CHANNEL_0);
    this->fadeAmount = ANALOG_VALUEMAX / (this->period / 20);
    // ledcWriteTone(LEDC_CHANNEL_0, 5000);
}

void LED_CONTRLLER :: blink(){
    digitalWrite(pinNum, HIGH);
    delay(period / 2);
    digitalWrite(pinNum, LOW); 
    delay(period / 2);
}

void LED_CONTRLLER :: fade(){ 
    ledcAnalogWrite(LEDC_CHANNEL_0, this->brightness);
    this->brightness = this->brightness + this->fadeAmount;
    if (this->brightness <= 0 || this->brightness >= ANALOG_VALUEMAX) {
        this->fadeAmount = -this->fadeAmount;
    }
    vTaskDelay(20);
}

void LED_CONTRLLER :: setPeriod(uint period){
    this->period = period;
    this->fadeAmount = ANALOG_VALUEMAX / (period / 20);
}

void LED_CONTRLLER :: setMode(bool state){
    if (state != this->state){
        if(state){
            pinMode(pinNum, OUTPUT);
            this->state = true;
        }else{
            ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT);
            ledcAttachPin(pinNum, LEDC_CHANNEL_0);
            this->state = false;
        }
    }
}

void LED_CONTRLLER :: mainloop(){
    if(this->state){
        this->blink();
    }else{
        this->fade();
    }
}

#endif